<?php
namespace Todo\Service;
use Todo\Model\FilesModel;

/**
 * Created by PhpStorm.
 * User: yepanpan
 * Date: 2016/8/8
 * Time: 17:08
 */
class FileService extends BaseService
{
    private static $__INSTANCE = null;

    public static function getInstance(){
        if(!self::$__INSTANCE) self::$__INSTANCE = new FileService();

        return self::$__INSTANCE;
    }

    /**
     * 验证文件是否存在
     * @param string $dbPath 数据库保存的路径
     * @return bool
     */
    public function checkFileExist($dbPath){
        return file_exists(C('FILE_UPLOAD.rootPath').$dbPath);
    }

    /**
     * 验证并创建目录
     * @param string $dirPath 目录名称
     */
    public function mkDir($dirPath){
        $fullPath = C('FILE_UPLOAD.rootPath').$dirPath;
        if(!file_exists($fullPath)) @mkdir($fullPath, 0777, true);
    }

    /**
     * 判断指定md5和sha1值的文件是否在数据库中有记录，如果有，则返回文件信息
     * @param string $md5 文件的MD5信息
     * @param string $sha1 文件的SHA1信息
     * @return array|false
     */
    public function dbExist($md5, $sha1){
        return D('Todo/Sys/Files')->findOne(array('md5'=>$md5, 'sha1'=>$sha1), true);
    }

    /**
     * 保存已经上传的文件，去除重复文件
     * @param string $filePath 文件保存路径
     * @param string $fileName 源文件名
     * @return array
     */
    public function saveUploadFile($filePath, $fileName, $md5='', $sha1=''){
        $data = array(
            'md5' => $md5 ? $md5 : md5_file($filePath),
            'sha1' => $sha1 ? $sha1 : sha1_file($filePath)
        );
        $info = D('Todo/Sys/Files')->findOne($data);
        if($info) {
            @unlink($filePath);
            return $info;
        }

        $data['name'] = $fileName;
        $data['path'] = $filePath;
        $data['exts'] = $this->getFileExt($filePath);
        $data['size'] = filesize($filePath);
        $data['upload_time'] = NOW_TIME;
        $data['upload_user'] = LoginService::getInstance()->getCurrentUser('id');
        $data['id'] = D('Todo/Sys/Files')->insert($data);
        return $data;
    }

    /**
     * 更新文件路径
     * @param int $fileId 文件ID
     * @param string $path 新的文件路径
     * @return int
     */
    public function updatePath($fileId, $path){
        return D('Todo/Sys/Files')->where(array('id'=>$fileId))->save(array('path'=>$path));
    }

    /**
     * 获取要存储到数据库的路径
     * @param $savePath
     * @param $fileName
     * @return string
     */
    public function getDbPath($savePath, $fileName){
        $type = 'file';
        $ext = $this->getFileExt($fileName);
        if(in_array($ext, explode(',', C('FILE_UPLOAD.image_exts')))) $type = 'image';
        if(in_array($ext, explode(',', C('FILE_UPLOAD.video_exts')))) $type = 'video';
        if(in_array($ext, explode(',', C('FILE_UPLOAD.doc_exts')))) $type = 'doc';
        $path = C('FILE_UPLOAD.rootPath'). C('FILE_UPLOAD.'.$type.'Folder').'/'.$savePath;
        if(!file_exists($path)) @mkdir($path, 0775, true);
        $path .=  '/'.NOW_TIME.'.'.$ext;
        if(file_exists($path)) $path .=  '/' . NOW_TIME. rand(0,10000) . '.' . $ext;
        return $path;
    }

    /**
     * 获取文件的扩展名
     * @param string $fileName 文件名或路径
     * @return string
     */
    public function getFileExt($fileName){
        return strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
    }

    /**
     * 根据文件ID获取文件对外的URL路径
     * @param int $fileId 文件ID
     * @return string
     */
    public function getUrlByFileId($fileId){
        $filePath = D('Todo/Sys/Files')->keyFind($fileId, 'path');
        return $this->getUrlByPath($filePath);
    }

    /**
     * 根据文件保存路径获取文件对外的URL路径
     * @param string $filePath 文件保存路径
     * @return string
     */
    public function getUrlByPath($filePath){
        return substr($filePath, 2);
    }

    /**
     * 根据扩展名，判断文件类型
     * @param $exts
     * @return string
     */
    public function getFileType($exts){
        switch ($exts) {
            case 'doc':
            case 'docx':
            case 'ppt':
            case 'pptx':
            case 'xls':
            case 'xlsx':
            case 'pdf':
                return 'doc';
                break;
            case 'wmv':
            case 'flv':
            case 'mp4':
            case 'rm':
            case 'rmvb':
            case 'avi':
            case 'mkv':
            case '3gp':
                return 'video';
                break;
            default:
                return 'info';
                break;
        }
    }

    /**
     * 下载文件
     * @param int $fileId 文件ID
     * @param string $format=pack 下载格式:pack=打包,source=源文件
     * @return bool
     */
    public function download($fileId){
        $fileModel = new FilesModel();
        $fileInfo = $fileModel->keyFind($fileId);
        if(!$fileInfo){
            $this->setError('文件不存在或者已经删除!');
            return false;
        }
        Files::download(C('FILE_UPLOAD.rootPath').$fileInfo['path'], $fileInfo['name']);
    }


    /**
     * 基于一级缓存的文件查询
     * @param $fileId
     * @param bool|string $field
     */
    public function cacheFindFile($fileId, $field=true){
        if(!$fileId) return '';
        $fileInfo = self::$CACHES[$fileId];
        if(!$fileInfo){
            $fileInfo = D('Todo/Sys/Files')->keyFind($fileId);
            self::$CACHES[$fileId]= $fileInfo;
        }
        if(!$fileInfo) return null;
        return $field===true ? $fileInfo : $fileInfo[$field];
    }
}